﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CodeCamp.Test.DataConversion
{
    public class TestBase
    {
        private static class BaseTags
        {
            internal const string userIdentityIssuer = "userIdentityIssuer";
            internal const string userIdentityProvider = "userIdentityProvider";
            internal const string userIdentityClaimType = "userIdentityClaimType";
            internal const string verbose = "verbose";
        }

        protected const int zero = 0;
        private TestContext testContextInstance;
        private Nullable<bool> _verbose;

        public TestBase()
        {
            _verbose = null;
        }

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        protected bool Verbose
        {
            get
            {
                if (!_verbose.HasValue)
                {
                    string verbose = ConfigurationManager.AppSettings["verbose"];
                    if (!string.IsNullOrWhiteSpace(verbose) && verbose.Trim().ToLower() == "true")
                        _verbose = true;
                    else
                        _verbose = false;
                }
                return _verbose.Value;
            }
        }

        protected bool GetAppSettingBool(string key, Nullable<bool> defaultValue)
        {
            Assert.IsNotNull(key);
            Assert.AreNotEqual(0, key.Length);
            string rawSetting = ConfigurationManager.AppSettings[key];
            Nullable<bool> setting = null;
            if (string.IsNullOrWhiteSpace(rawSetting))
            {
                setting = defaultValue;
            }
            else
            {
                if (rawSetting.Trim().ToLower().Equals("true"))
                    setting = true;
                else
                    setting = false;
            }
            Assert.IsTrue(setting.HasValue, "No value found for key \"{0}\" and no default set.", key);
            return setting.Value;
        }


        protected string GetAppSettingString(string key)
        {
            string appSetting = ConfigurationManager.AppSettings[key];
            Assert.IsNotNull(appSetting, "GetAppSettingString(\"{0}\") - no value found.", key);
            Assert.AreNotEqual(0, appSetting.Trim().Length, "GetAppSettingString(\"{0}\") - value is empty.", key);
            return appSetting;
        }

        protected string UserIdentityClaimType
        {
            get { return GetAppSettingString(BaseTags.userIdentityClaimType); }
        }

        protected string UserIdentityIssuer
        {
            get { return GetAppSettingString(BaseTags.userIdentityIssuer); }
        }

        protected string UserIdentityProvider
        {
            get { return GetAppSettingString(BaseTags.userIdentityProvider); }
        }

        protected void ReportException(Exception ex)
        {
            TestContext.WriteLine("{1}: {2}{0}{3}",
                Environment.NewLine,
                ex.GetType(),
                ex.Message,
                ex.StackTrace);
        }

        protected void ReportException(System.Data.Entity.Infrastructure.DbUpdateException ex)
        {
            TestContext.WriteLine("{1}: {2}{0}{3}",
                Environment.NewLine,
                ex.GetType(),
                ex.Message,
                ex.StackTrace);
            if (ex.Entries != null)
            {
                foreach (System.Data.Entity.Infrastructure.DbEntityEntry entry in ex.Entries)
                {
                    TestContext.WriteLine("\tEntity {0} has state {1} and {2} values.",
                        entry.Entity.GetType(),
                        entry.State,
                        entry.CurrentValues.PropertyNames.Count());
                    foreach (string propName in entry.CurrentValues.PropertyNames)
                    {
                        TestContext.WriteLine("\t\t{0}: {1}",
                            propName,
                            entry.CurrentValues[propName]);
                    }
                }
            }
            if (ex.InnerException != null)
            {
                if (ex.InnerException.GetType() == typeof(System.Data.UpdateException))
                {
                    ReportException(ex.InnerException as System.Data.UpdateException);
                }
                else
                {
                    ReportException(ex.InnerException);
                }
            }
        }

        protected void ReportException(System.Data.UpdateException ex)
        {
            TestContext.WriteLine("{1}: {2}{0}{3}",
                Environment.NewLine,
                ex.GetType(),
                ex.Message,
                ex.StackTrace);
            if (ex.InnerException != null)
            {
                ReportException(ex.InnerException);
            }
        }

        protected void ReportException(System.Data.Entity.Validation.DbEntityValidationException ex)
        {
            Assert.IsNotNull(ex);
            TestContext.WriteLine("{1}: {2}{0}{3}",
                Environment.NewLine,
                ex.GetType(),
                ex.Message,
                ex.StackTrace);
            if (ex.EntityValidationErrors != null)
            {
                TestContext.WriteLine("\t-----");
                foreach (System.Data.Entity.Validation.DbEntityValidationResult result in ex.EntityValidationErrors)
                {
                    TestContext.WriteLine("\t{0}", result.Entry);
                    if (result.ValidationErrors != null)
                    {
                        foreach (System.Data.Entity.Validation.DbValidationError error in result.ValidationErrors)
                        {
                            TestContext.WriteLine("\t\t{0}: {1}",
                                error.PropertyName,
                                error.ErrorMessage);
                        }
                    }

                }
            }
            TestContext.WriteLine("----------");
        }

        protected void ReportException(System.Data.DataException ex)
        {
            Assert.IsNotNull(ex);
            TestContext.WriteLine("{1}: {2}{0}{3}",
                Environment.NewLine,
                ex.GetType(),
                ex.Message,
                ex.StackTrace);
            Exception innerEx = ex.InnerException;
            while (innerEx != null)
            {
                TestContext.WriteLine("----------");
                if (innerEx.GetType() == typeof(System.Data.Entity.Validation.DbEntityValidationException))
                {
                    ReportException(innerEx as System.Data.Entity.Validation.DbEntityValidationException);
                }
                else
                {
                    ReportException(innerEx);
                }
                innerEx = innerEx.InnerException;
            }
            TestContext.WriteLine("----------");
        }

    }
}
